 /*****************************************************************************
 * (C) Copyright 2011 Atech-Automotive
 * FILE NAME:    hwa_a2dActions.h
 * DESCRIPTION:  
 * DATE BEGUN:   
 * BY:           
 * PRODUCT NAME: 
 * APPLICATION:  
 * TARGET H/W:   
 * DOC REF:
 *****************************************************************************
 */

#define hwa_a2dActions_c


/* #include */
#include <string.h>

#include "sys_micro.h"
#include "system.h"
#include "drv_a2d.h"
#include "hwa_a2dActions.h"
#include "hwa_inputs.h"
/* #define */
#define VOLTAGE_DELAY_TIME		150

/* typedef */
typedef struct
{
    BOOL   low_vbat_flag;
    UINT16 low_vbat_count;

    BOOL   high_vbat_flag;
    UINT16 high_vbat_count;

} A2DAction_DTC_S;

/* static variables */
static A2DAction_DTC_S s_a2d_action_dtc;

//static UINT8 F_noSwap;
static UINT8 vBatDArray[A2D_AVG_SIZE];   

/* static constants */
void hwa_a2d__v_checkVbatDTCStatus(void);


/* static function prototypes */
//UINT8 hwa_a2d_u8_getFilteredA2D(UINT8 size, const UINT8 *const pArray);


/*****************************************************************************/
/**
 * Function Name: void initA2dActions(void)
 * Description:   Fill arrays with A2D samples
 *
 * Param:   none
 * Return:  none
 * Author:  rrosenba
 *****************************************************************************/
void hwa_a2d_v_iniA2dActions(void)
{
    UINT8 i;   /* counter variable */
    
    for(i = 0; i < A2D_AVG_SIZE; i++)
    {
        /* read voltage and write A2D value to buffer */
        vBatDArray[i] = drv_a2d_u8_readData8Bit(CH_S_VBAT_IN_AN);
    }
}

/*****************************************************************************/
/**
 * Function Name: void a2dActions(void)
 * Description:   Write one A2D sample to each array
 *
 * Param:   none
 * Return:  none
 * Author:  rrosenba
 *****************************************************************************/
void hwa_a2d_v_a2dActions(void)
{
    static UINT8 i = 0,j = 0;     /* counter variable */
    static UINT8 lowVCounter = 0;
    static UINT8 highVCounter = 0;
    /* read voltage and write A2D value to buffer */
    vBatDArray[i] = drv_a2d_u8_readData8Bit(CH_S_VBAT_IN_AN);
//    u8_vBatDCurrent = vBatDArray[i];
    
    if(++i >= A2D_AVG_SIZE)
    {
        i = 0;
    }
    vBatD = hwa_a2d_u8_getFilteredA2D(A2D_AVG_SIZE, vBatDArray);
    
    hwa_a2d__v_checkVbatDTCStatus();                     	
}


/*****************************************************************************/
/**
 * Function Name: hwa_a2d__v_checkVbatDTCStatus
 * Description:  check battery dtc status
 *
 * Param:   param
 * Return:  status
 * Author:  AF
 * *****************************************************************************/
 void hwa_a2d__v_checkVbatDTCStatus(void)
 {  
   if(hwa_inputs_u8_inputsGetVBatD() < VBAT_9_5V)
    {
        if(s_a2d_action_dtc.low_vbat_count > VBAT_POWER_DTC_DELAY_TIME_CNT)
        {
            s_a2d_action_dtc.low_vbat_flag = ON;
        }
        else
        {
            s_a2d_action_dtc.low_vbat_count++;
        }
    }
    else
    {
        s_a2d_action_dtc.low_vbat_flag  = OFF;
        s_a2d_action_dtc.low_vbat_count = 0x00;
    }

    //////////////////////////////////

    if(hwa_inputs_u8_inputsGetVBatD() > VBAT_16V)
    {
        if(s_a2d_action_dtc.high_vbat_count > VBAT_POWER_DTC_DELAY_TIME_CNT)
        {
            s_a2d_action_dtc.high_vbat_flag = ON;
        }
        else
        {
            s_a2d_action_dtc.high_vbat_count++;
        }
    }
    else
    {
        s_a2d_action_dtc.high_vbat_flag  = OFF;
        s_a2d_action_dtc.high_vbat_count = 0x00;
    }
 }
  
/*****************************************************************************/
/**
 * Function Name: hwa_a2d__u8_getVbatDTCStatus
 * Description:  get battery dtc status
 *
 * Param:   param
 * Return:  status
 * Author:  AF
 * *****************************************************************************/
 UINT8 hwa_a2d__u8_getVbatDTCStatus(UINT8 cmd)
 {  
	if (cmd == LOW_V)
	{
		return s_a2d_action_dtc.low_vbat_flag;
	}
	else if (cmd == HI_V)
	{
		return s_a2d_action_dtc.high_vbat_flag;
	}
	else
	{
		//maybe reset system
	}
	     
	return FALSE;
 }
/*****************************************************************************/
/**
 * Function Name: UINT8 hwa_a2d_u8_normA2D(UINT8 value, UINT8 ref)
 * Description:   Normalize value to reference value
 * Note : when you are using normA2D, parameters need to be both instant collected
 *        data or both filtered data,otherwise some misjudgement will occur when 
 *        cranking(Vbat drop).

 * Param:   value - value to be normalized
 *          ref   - reference
 * Return:  Normalized value (max. 0xFF; 0xFF if ref == 0)
 * Author:  rrosenba
 *****************************************************************************/
UINT8 hwa_a2d_u8_normA2D(UINT8 value, UINT8 ref)
{
    UINT16 norm = 0xFF;

    if(value>=240)
    {
        NOP();//just for debug node
        return 0xFF; 
    }
    
    if (ref)
    {
        norm = ((UINT16) value * NORM) / ((UINT16) ref + D_CORR);  
        if (norm > 0xFF)
        {
            return 0xFF;
        }
    }
    return (UINT8) norm;
}

/*****************************************************************************/
/**
 * Function Name: UINT8 hwa_a2d_u8_getFilteredA2D(UINT8 size, const UINT8 *const pArray)
 * Description:   Filter A2D values by sorting them in ascending order. The
 *                algorithm used is an optimized bubble sort.
 * Note 1:        Array size should be odd to be able to return the middle val!
 * Note 2:        Array size must be smaller or equal than A2D_AVG_SIZE!
 *
 * Param:   size    - size of array
 *          pArray - pointer to beginning of A2D sample array
 * Return:  Middle (median) value of A2D array
 * Author:  rrosenba
 *****************************************************************************/
UINT8 hwa_a2d_u8_getFilteredA2D(UINT8 size, const UINT8 *const pArray)
{
    UINT8 pass;      /* outer counter variable */
    UINT8 i;         /* inner counter variable */
    UINT8 tmp;
    UINT8 halfSize;
    UINT8 tmpArray[A2D_AVG_SIZE];
    
    /* copy array to leave pArray as is in order to discard the oldest value
       the next time a sample is added */
    (void)memcpy(tmpArray, pArray, size);
    
    /* 
     * Sort array in ascending order.
     * We terminate sorting if
     *  - the array is in proper order and doesn't need further sorting
     *  - the upper half of the array is in proper order incl. the middle value
     */
    halfSize = (size >> 1);
    for(pass = 1; pass <= (halfSize + 1); pass++)
    {
        F_noSwap = TRUE;
        for(i = 0; i < (size - pass); i++)
        {
            if(tmpArray[i] > tmpArray[i+1])
            {
                tmp           = tmpArray[i];
                tmpArray[i]   = tmpArray[i+1];
                tmpArray[i+1] = tmp;
                F_noSwap      = FALSE;
            }
        }
        /* If no swaps have been made the array is in proper order */
        if(F_noSwap == TRUE)
        {
            break;
        }
    }
    tmp = tmpArray[halfSize];   /* NEEDED! Workaraound for optimizer bug!!!! */
    return (tmp);               /* return value in the middle of the array */
}
/***********************end of a2dActions.c***********************************/

/******************************************************************************
 Revision Notes:

For each change to this file, be sure to record:
1. Who made the change and when the change was made.
2. Why the change was made and the intended result.

  Date     By     Reason For Change
mm/dd/yy  XXX     -----------------

******************************************************************************/
